#region Using directives

using System;
using System.Collections.Generic;

#endregion

namespace Weazel.Gezel.Simulator.Reference
{
  /// <summary>
  /// Records the set of signalflowgraphs which
  /// are active in the current simulation cycle.
  /// The SignalContext object can use instances
  /// of this class to compute the intersection of
  /// active sfg's and possible signal definers to
  /// determine what signal currently drives the 
  /// signal to which the SignalContext instance 
  /// belongs.
  /// </summary>
  public class DatapathContext
  {
    /// <summary>
    /// Enumerates the possible outcomes of the
    /// Lookup() operation
    /// </summary>
    public enum LookupResult
    {
      None, 
      Single,
      Multiple
    }

    /// <summary>
    /// The set of id's for the flowgraphs which
    /// are active in the current simulation cycle
    /// </summary>
    private readonly List<Symid> activeSignalFlowGraphs;
    
    /// <summary>
    /// Current controlstep of the controller
    /// </summary>
    private int currentControlStep;
    public int CurrentControlStep
    {
      get
      {
        return currentControlStep;
      }
      set
      {
        currentControlStep = value;
      }
    }

    /// <summary>
    /// Constructs a new DatapathContext with an empty
    /// set of active signalflowgraphs
    /// </summary>
    public DatapathContext()
    {
      activeSignalFlowGraphs = new List<Symid>();
    }

    /// <summary>
    /// Clears the list of active signalflowgraphs
    /// </summary>
    public void Clear()
    {
      activeSignalFlowGraphs.Clear();
    }

    /// <summary>
    /// Marks the referenced signalflowgraph as active
    /// in the current simulation cycle
    /// </summary>
    /// <param name="sfgId"></param>
    public void ActivateSignalFlowGraph(int sfgId)
    {
      activeSignalFlowGraphs.Add(sfgId);
    }

    /// <summary>
    /// Computes the intersection of a set of active signalflowgraphs
    /// and the set of defining signalflowgraphs (for a particular signal)
    /// and returns the id of the defining signal if only one result
    /// is in the intersection (the normal case). The computed intersection
    /// can have zero, one or more members which is signalled by the 
    /// return LookupResult return value which enumerates these three cases
    /// </summary>
    /// <param name="definingSfgs">the set of defining sfgs for a signal</param>
    /// <param name="intersectionId">the id of the single signal in the 
    /// intersection if only one result in set
    /// </param>
    /// <returns></returns>
    public LookupResult Lookup(List<Symid> definingSfgs, out Symid intersectionId)
    {
      List<Symid> intersectionSet = new List<Symid>();
      
      // compute intersection between
      // defining and active signalflowgraphs
      // for the coresponding signal
      foreach (Symid sid in definingSfgs)
        if (activeSignalFlowGraphs.Contains(sid))
          intersectionSet.Add(sid);

			

      // check results
      if (intersectionSet.Count == 1)
      {
        // most common case, should be first
        intersectionId = intersectionSet[0];
        return LookupResult.Single;        
      }
      else if (intersectionSet.Count > 1)
      {
        // error case
        intersectionId = Symid.NOSYMBOL;
        return LookupResult.Multiple;
      }
      else
      {
        // error case
        intersectionId = Symid.NOSYMBOL;
        return LookupResult.None;
      }
    }

    /// <summary>
    /// Returns true iff the signal flow graph
    /// with the given id is active in the current
    /// simulation cycle and false otherwise.
    /// </summary>
    /// <param name="sfg">unique id of the signalflowgraph</param>
    /// <returns>true iff sfg is active in current cycle</returns>
    public bool IsSignalFlowGraphActive(Symid sfgId)
    {
      return activeSignalFlowGraphs.Contains(sfgId);
    }
  }
}